package com.hfi.ood.litejunit.v3.framework.runners;

import com.hfi.ood.litejunit.v3.framework.manipulation.*;
import com.hfi.ood.litejunit.v3.framework.notification.RunNotifier;
import com.hfi.ood.litejunit.v3.framework.runner.Description;
import com.hfi.ood.litejunit.v3.framework.runner.Runner;

import java.util.*;

/**
 * @author ChangLiang
 * @date 2020/5/28
 */
public class CompositeRunner extends Runner implements Filterable, Sortable {
    private final List<Runner> fRunners= new ArrayList<Runner>();
    private final String fName;

    public CompositeRunner(String name) {
        fName= name;
    }

    @Override
    public void run(RunNotifier notifier) {
        for (Runner each : fRunners) {
            each.run(notifier);
        }
    }

    @Override
    public Description getDescription() {
        Description spec= Description.createSuiteDescription(fName);
        for (Runner runner : fRunners) {
            spec.addChild(runner.getDescription());
        }
        return spec;
    }

    public List<Runner> getRunners() {
        return fRunners;
    }

    public void addAll(List<? extends Runner> runners) {
        fRunners.addAll(runners);
    }

    public void add(Runner runner) {
        fRunners.add(runner);
    }

    @Override
    public void filter(Filter filter) throws NoTestsRemainException {
        for (Iterator iter = fRunners.iterator(); iter.hasNext();) {
            Runner runner= (Runner) iter.next();
            if (filter.shouldRun(runner.getDescription())) {
                filter.apply(runner);
            } else {
                iter.remove();
            }
        }
    }

    protected String getName() {
        return fName;
    }

    @Override
    public void sort(final Sorter sorter) {
        Collections.sort(fRunners, new Comparator<Runner>() {
            @Override
            public int compare(Runner o1, Runner o2) {
                return sorter.compare(o1.getDescription(), o2.getDescription());
            }
        });
        for (Runner each : fRunners) {
            sorter.apply(each);
        }
    }
}
